package com.yiduo.outpost.ucenter.service.impl;

import cn.hutool.core.util.IdUtil;
import com.yiduo.outpost.core.model.entity.User;
import com.yiduo.outpost.core.model.enums.UserRole;
import com.yiduo.outpost.core.model.enums.UserStatus;
import com.yiduo.outpost.core.redis.props.RedisConstant;
import com.yiduo.outpost.core.security.jwt.JwtProperties;
import com.yiduo.outpost.core.security.jwt.JwtTokenGenerator;
import com.yiduo.outpost.ucenter.model.dto.SignUpRequestBody;
import com.yiduo.outpost.ucenter.service.SessionService;
import com.yiduo.outpost.ucenter.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.Optional;

@Service
public class SessionServiceImpl implements SessionService {

    @Autowired
    private JwtTokenGenerator tokenGenerator;

    @Autowired
    private AuthenticationManagerBuilder authenticationManagerBuilder;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private UserService userService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 登录验证
     *
     * @param loginKey
     * @param password
     * @return
     */
    public Authentication authenticate(String loginKey, String password) {
        Authentication authentication = authenticationManagerBuilder.getObject()
                .authenticate(new UsernamePasswordAuthenticationToken(loginKey, password));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        return authentication;
    }

    /**
     * 注册
     *
     * @param signUpRequestBody
     * @return
     */
    public User signUp(SignUpRequestBody signUpRequestBody) {
        User user = new User();
        user.setUsername(signUpRequestBody.getUsername())
                .setPassword(passwordEncoder.encode(signUpRequestBody.getPassword()))
                .setEmail(signUpRequestBody.getEmail()).setRole(UserRole.ROLE_ADMIN).setStatus(UserStatus.ENABLE);
        userService.save(user);
        return user;
    }

    /**
     * 生成token
     */
    public String createToken(Authentication authentication, Duration ttl) {
        User user = (User) authentication.getPrincipal();
        String jwtToken = tokenGenerator.generateToken(user.getId(), user.getUsername(), ttl, user.getRole()
                .toString(), IdUtil.fastUUID());
        return jwtToken;
    }

    /**
     * 刷新token
     */
    @Override
    public void refreshToken(Long userId, String token, Duration ttl) {
        redisTemplate.opsForValue().set(RedisConstant.USER_SESSION_TOKEN_KEY + userId, token, Optional.ofNullable(ttl)
                .orElse(jwtProperties.getExpireTime()).getSeconds(), java.util.concurrent.TimeUnit.SECONDS);
        userService.clearUserCache(userId);
    }

    /**
     * 登出清理缓存
     */
    @Override
    public void logout(Long userId) {
        redisTemplate.delete(RedisConstant.USER_SESSION_TOKEN_KEY + userId);
        userService.clearUserCache(userId);
    }

}